/**
 * 
 */
package fr.paulmasson.jfreex.ui;

import java.util.ArrayList;
import java.util.Calendar;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Link;
import org.eclipse.swt.widgets.ProgressBar;
import org.eclipse.swt.widgets.Scale;

import com.javadude.swt.layouts.BorderLayout;
import com.javadude.swt.layouts.FlowLayout;
import com.javadude.swt.layouts.GridLayout;

import fr.paulmasson.jfreex.channels.CantRetrieveInfo;
import fr.paulmasson.jfreex.channels.ChannelInfo;
import fr.paulmasson.jfreex.channels.Info;
import fr.paulmasson.jfreex.channels.LiveChannel;
import fr.paulmasson.jfreex.channels.LiveChannel.Definition;

/**
 * @author Paul MASSON : contact@paulmasson.fr
 * @version 11.7.8
 */
public class InfosPanel {

	private static Label desc;
	private static Label icon;
	private static Link title;
	private static Label subtitle;
	private static Label start;
	private static Label end;
	private static ProgressBar progressBar;

	private static ChannelInfo info_getter = new ChannelInfo();

	private static LiveChannel current_channel = null;
	private static long current_media_start;
	private static long current_media_stop;
	private static Thread t;
	private static Combo defs;

	private static Image playIcon;
	private static Image pauseIcon;
	private static Image stopIcon;
	private static Image backToLiveIcon;

	private static boolean paused = false;

	private static ArrayList<ChannelsListListener> listeners = new ArrayList<ChannelsListListener>();
	private static Button play_paused;
	private static long pauseStart;
	private static Button directStart;
	private static Button stop;
	private static Scale vol_scale;
	private static Label vol_minus;
	private static Label vol_max;
	private Label titleNext;
	private Label subtitleNext;
	private Label lengthNext;
	private Label length;

	public void addChannelsListListener(ChannelsListListener listener) {
		listeners.add(listener);
	}

	private static void fireChannelChanged(LiveChannel channel, Definition def) {
		for (ChannelsListListener listener : listeners) {
			listener.ChannelChanged(channel, def);
		}
	}

	private static void fireChannelStopped() {
		for (ChannelsListListener listener : listeners) {
			listener.ChannelStopped();
		}
	}

	private static void fireAudioVolumeChanged(int vol) {
		for (ChannelsListListener listener : listeners) {
			listener.audioVolumeChange(vol);
		}
	}

	private static void firePauseMedia() {
		for (ChannelsListListener listener : listeners) {
			listener.pause();
		}
	}

	private static void firePlayMedia() {
		for (ChannelsListListener listener : listeners) {
			listener.play();
		}
	}
	
	private static void fireBackToLive() {
		for (ChannelsListListener listener : listeners) {
			listener.backToLive();
		}
	}
	

	public InfosPanel() {
		playIcon = new Image(Display.getCurrent(), this.getClass()
				.getResourceAsStream("/data/actions/play.png"));
		pauseIcon = new Image(Display.getCurrent(), this.getClass()
				.getResourceAsStream("/data/actions/pause.png"));
		stopIcon = new Image(Display.getCurrent(), this.getClass()
				.getResourceAsStream("/data/actions/stop.png"));
		backToLiveIcon = new Image(Display.getCurrent(), this.getClass()
				.getResourceAsStream("/data/actions/back_to_live.png"));
	}

	public Composite create(Composite container, final Display display) {
		Composite main_panel = new Composite(container, SWT.BORDER);
		main_panel.setLayout(new BorderLayout());

		Composite channel_info = new Composite(main_panel, SWT.NONE);
		channel_info.setLayout(new BorderLayout(5, 5));
		channel_info.setLayoutData(BorderLayout.NORTH);

		icon = new Label(channel_info, SWT.NONE);
		icon.setLayoutData(BorderLayout.WEST);
		icon.setText("               ");
		icon.setSize(38, 38);

		Composite tmp = new Composite(channel_info, SWT.NONE);
		tmp.setLayout(new BorderLayout());
		tmp.setLayoutData(BorderLayout.EAST);
		defs = new Combo(tmp, SWT.READ_ONLY);
		defs.setLayoutData(BorderLayout.NORTH);
		defs.setItems(new String[] { "Haute définition", "Définition standard",
				"Basse définition" });
		defs.setText("Définition standard");
		defs.setEnabled(false);

		defs.addSelectionListener(new SelectionListener() {

			@Override
			public void widgetSelected(SelectionEvent arg0) {
				int index = defs.getSelectionIndex();
				fireChannelChanged(current_channel,
						current_channel.getDefs()[index]);
			}

			@Override
			public void widgetDefaultSelected(SelectionEvent arg0) {
			}
		});

		Composite info_panel = new Composite(channel_info, SWT.NONE);
		GridLayout flow = new GridLayout(5,2);
		info_panel.setLayout(flow);
		info_panel.setLayoutData(BorderLayout.CENTER);

		desc = new Label(info_panel, SWT.NONE);
		desc.setText("");
		new Label(info_panel, SWT.NONE).setText("À suivre :");
		title = new Link(info_panel, SWT.NONE);
		title.setText("");
		titleNext = new Label(info_panel, SWT.NONE);
		subtitle = new Label(info_panel, SWT.NONE);
		subtitle.setText("");
		subtitleNext = new Label(info_panel, SWT.NONE);
		length = new Label(info_panel, SWT.NONE);
		lengthNext = new Label(info_panel, SWT.NONE);
		new Label(info_panel, SWT.NONE);
		new Label(info_panel, SWT.NONE);
		

		Composite timePanel = new Composite(main_panel, SWT.NONE);
		timePanel.setLayout(new BorderLayout(5, 5));
		timePanel.setLayoutData(BorderLayout.CENTER);
		start = new Label(timePanel, SWT.NONE);
		start.setLayoutData(BorderLayout.WEST);
		start.setText("00:00");
		start.setEnabled(false);
		end = new Label(timePanel, SWT.NONE);
		end.setLayoutData(BorderLayout.EAST);
		end.setText("00:00");
		end.setEnabled(false);
		progressBar = new ProgressBar(timePanel, SWT.SMOOTH);
		progressBar.setLayoutData(BorderLayout.CENTER);
		progressBar.setEnabled(false);

		Composite subMain = new Composite(main_panel, SWT.NONE);
		subMain.setLayoutData(BorderLayout.SOUTH);
		subMain.setLayout(new BorderLayout(5, 5));

		Composite direct = new Composite(subMain, SWT.NONE);
		FlowLayout f = new FlowLayout(SWT.HORIZONTAL);
		direct.setLayout(f);
		direct.setLayoutData(BorderLayout.CENTER);
		
		Label directLabel = new Label(direct, SWT.NONE);
		directLabel.setText("Décalage avec le direct : ");
		
		directStart = new Button(direct, SWT.PUSH);
		directStart.setLayoutData(BorderLayout.CENTER);
		directStart.setText("Pas de décalage");
		directStart.setEnabled(false);
		directStart.setImage(backToLiveIcon);
		directStart.addSelectionListener(new SelectionListener() {
			
			@Override
			public void widgetSelected(SelectionEvent arg0) {
				fireBackToLive();
				directStart.setText("Pas de décalage");
				directStart.setEnabled(false);
				paused = false;		
				play_paused.setImage(pauseIcon);		
			}
			
			@Override
			public void widgetDefaultSelected(SelectionEvent arg0) {}
		});

		Composite controlPanel = new Composite(subMain, SWT.NONE);
		controlPanel.setLayoutData(BorderLayout.SOUTH);
		FlowLayout fill = new FlowLayout(SWT.HORIZONTAL);
		controlPanel.setLayout(fill);

		

		stop = new Button(controlPanel, SWT.PUSH);
		stop.setImage(stopIcon);
		stop.addMouseListener(new MouseListener() {
			@Override
			public void mouseUp(MouseEvent arg0) {
				fireChannelStopped();
			}

			@Override
			public void mouseDown(MouseEvent arg0) {
			}

			@Override
			public void mouseDoubleClick(MouseEvent arg0) {
			}
		});
		stop.setEnabled(false);

		play_paused = new Button(controlPanel, SWT.PUSH);
		play_paused.setImage(pauseIcon);
		play_paused.setEnabled(false);

		play_paused.addMouseListener(new MouseListener() {
			@Override
			public void mouseUp(MouseEvent arg0) {
				PlayPause();
			}

			@Override
			public void mouseDown(MouseEvent arg0) {
			}

			@Override
			public void mouseDoubleClick(MouseEvent arg0) {
			}
		});

		
		vol_minus = new Label(controlPanel, SWT.NONE);
		vol_minus.setText("Volume :   -");
		vol_minus.setEnabled(false);
		vol_scale = new Scale(controlPanel, SWT.NONE);
		vol_scale.setEnabled(false);
		vol_scale.setMaximum(200);
		vol_scale.setMinimum(0);
		vol_scale.setSelection(100);
		vol_scale.addSelectionListener(new SelectionListener() {
			@Override
			public void widgetSelected(SelectionEvent arg0) {
				fireAudioVolumeChanged(vol_scale.getSelection());
			}

			@Override
			public void widgetDefaultSelected(SelectionEvent arg0) {
			}
		});
		vol_max = new Label(controlPanel, SWT.NONE);
		vol_max.setText("+");
		vol_max.setEnabled(false);

		t = new Thread() {
			public void run() {
				while (true) {
					try {
						Thread.sleep(1000);
					} catch (Throwable th) {
					}
					if (display.isDisposed())
						return;
					display.asyncExec(new Runnable() {
						public void run() {
							updateTimeProgress();
						}
					});
				}
			}
		};

		return main_panel;
	}

	protected static void PlayPause() {
		if (paused) {
			firePlayMedia();
			play_paused.setImage(pauseIcon);
		} else {
			firePauseMedia();
			play_paused.setImage(playIcon);
		}
		paused = !paused;
	}

	public void update(LiveChannel channel) {

		play_paused.setImage(pauseIcon);
		play_paused.setEnabled(true);
		current_channel = channel;
		paused = false;
		pauseStart = 0;
		directStart.setText("Pas de décalage");
		directStart.setEnabled(false);
		stop.setEnabled(true);
		start.setEnabled(true);
		end.setEnabled(true);
		vol_scale.setEnabled(true);
		defs.setEnabled(true);
		vol_minus.setEnabled(true);
		vol_max.setEnabled(true);
		
		
		try {
			Calendar c = Calendar.getInstance();
			
			
			ArrayList<Info> infos = info_getter.getCurrentTrack(channel, c.getTimeInMillis());
			Info info_current = infos.get(0); 
			Info next = infos.get(1);
			
			if (next.getTitle().equals("")) {
				long dec = c.getTimeInMillis() + (info_current.getEnd()- info_current.getStart())-1;
				ArrayList<Info> infos2 = info_getter.getCurrentTrack(channel, dec);
				next = infos2.get(1);
			}
			
			
			System.out.println(next.getTitle());
			System.out.println(next.getDesc());
			
			titleNext.setText(next.getTitle());
			subtitleNext.setText(next.getDesc());
			lengthNext.setText(lengthToString(next.getEnd()-next.getStart()));
			

			c.clear();
			c.setTimeInMillis(info_current.getStart());
			start.setText(String.format("%02d:%02d",
					c.get(Calendar.HOUR_OF_DAY), c.get(Calendar.MINUTE)));
			c.clear();
			c.setTimeInMillis(info_current.getEnd());
			end.setText(String.format("%02d:%02d", c.get(Calendar.HOUR_OF_DAY),
					c.get(Calendar.MINUTE)));

			current_media_start = info_current.getStart();
			current_media_stop = info_current.getEnd();

			updateTimeProgress();
			length.setText(lengthToString(info_current.getEnd()-info_current.getStart()));
			desc.setText(channel.getTitle().toUpperCase());
			title.setText("<a>"+info_current.getTitle()+"</a>");
			subtitle.setText(info_current.getDesc());
			try {
				icon.setImage(new Image(Display.getCurrent(), channel.getIconPath()));
			} catch (Exception e) {
			}

		} catch (CantRetrieveInfo e) {
		}
		if (!t.isAlive())
			t.start();

		String[] defs_tmp = new String[channel.getDefs().length];
		int i = 0;
		for (Definition def : channel.getDefs()) {
			defs_tmp[i] = channel.toStringDef(def);
			i++;
		}
		defs.setItems(defs_tmp);
		defs.setText(channel.toStringDef(channel.getCurrentDef()));

	}

	private void updateTimeProgress() {
		long currentTime = Calendar.getInstance().getTimeInMillis();
		progressBar.setData(String.format("%02d:%02d", Calendar.getInstance().get(Calendar.HOUR_OF_DAY), Calendar.getInstance().get(Calendar.MINUTE)));
		try {
			int percent = (int) ((currentTime - current_media_start) * 100 / (current_media_stop - current_media_start));
			progressBar.setSelection(percent);
			if (percent == 100 && current_channel != null) {
				update(current_channel);
			}
			if (paused) {
				pauseStart += 1;
				if (pauseStart>59) {
					directStart.setText((pauseStart/60) + " min. " + (pauseStart % 60) + " sec.");	
				} else {
					directStart.setText((pauseStart % 60) + " sec.");	
				}
				directStart.setEnabled(true);
			}
		} catch (ArithmeticException ex) {
			// System.err.println("Division by Zero!!");
		}
	}
	
	
	private String lengthToString(long length) {
		length /= 1000;
			long nb_hours = length/3600;
			length = length % 3600;
			long nb_minutes = length/60;
//			length = length % 60;
//			long nb_secondes = length;
			
			StringBuffer res = new StringBuffer();
			if (nb_hours == 1) {
				res.append(nb_hours + " heure");
			} else if (nb_hours > 1) {
				res.append(nb_hours + " heures");
			}
			if (nb_minutes == 1) {
				res.append((res.length()>0?" ":"") + nb_minutes + " minute");
			} else if (nb_minutes > 1) {
				res.append((res.length()>0?" ":"") + nb_minutes + " minutes");
			}
			
			return res.toString();
		
	}

}
